﻿using DotNetCommon.Extensions;
using System;
using System.Globalization;
using System.Text.RegularExpressions;

namespace DotNetCommon;
/// <summary>
/// 提供一组方法来帮助使用 <see cref="Regex"/>。
/// </summary>
public sealed class RegexHelper
{
    private RegexHelper() { }
    #region 电子邮箱格式校验
    private static readonly Regex _emailPrimaryRegex =
        new(@"(@)(.+)$", RegexOptions.Compiled, 200.Milliseconds());

    private static readonly Regex _emailSecondaryRegex =
        new(
            @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
            @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$",
            RegexOptions.Compiled | RegexOptions.IgnoreCase,
            250.Milliseconds());

    private readonly IdnMapping _idn = new();

    private bool _isValid = true;

    /// <summary>
    /// 将给定的<paramref name="input"/>判断是否为有效的电子邮件地址。
    /// <see href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format"/>
    /// </summary>
    private bool isValidEmail(string input)
    {
        if (input.IsNullOrWhiteSpace()) { return false; }

        _isValid = true;

        string replaced;
        try
        {
            replaced = _emailPrimaryRegex.Replace(input, DomainMapper);
        }
        catch (RegexMatchTimeoutException)
        {
            return false;
        }

        if (!_isValid) { return false; }

        try
        {
            return _emailSecondaryRegex.IsMatch(replaced);
        }
        catch (RegexMatchTimeoutException)
        {
            return false;
        }

        string DomainMapper(Match match)
        {
            var domainName = match.Groups[2].Value;
            try
            {
                domainName = _idn.GetAscii(domainName);
            }
            catch (ArgumentException)
            {
                _isValid = false;
            }
            return match.Groups[1].Value + domainName;
        }
    }
    #endregion

    /// <summary>
    /// 是否是正确的邮箱格式
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    internal static bool IsValidEmail(string input)
    {
        return new RegexHelper().isValidEmail(input);
    }
}